package com.zkq.graduate.interceptor;

import com.alibaba.fastjson.JSON;
import com.zkq.graduate.annotation.Admin;
import com.zkq.graduate.annotation.Student;
import com.zkq.graduate.annotation.Teacher;
import com.zkq.graduate.pojo.Permission;
import com.zkq.graduate.pojo.Role;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @Author zhangkaiqiang
 * @Date 2019/12/4  11:31
 * @Description TODO
 *
 * 权限过滤器,校验用户是否具备访问某个Controller的权限
 */
@Component
public class AuthInterceptor implements HandlerInterceptor {


	// https://www.cnblogs.com/itkk/archive/2017/08/28/7442500.html

	@Resource
	private RedisTemplate redisTemplate;


	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

		// 如果不是映射方法直接通过
		if(!(handler instanceof HandlerMethod)){
			return true;
		}

		HandlerMethod handlerMethod= (HandlerMethod) handler;
		Method method=handlerMethod.getMethod();

		// 对任何角色都可以访问的方法进行放行
		if(!method.isAnnotationPresent(Teacher.class)&&!method.isAnnotationPresent(Student.class)&&!method.isAnnotationPresent(Admin.class)){
			return true;
		}

		// 判断当前登录的用户是否具备允许访问的角色以及角色是否具备对应的url权限
		if(method.isAnnotationPresent(Teacher.class)){
			if(checkUserPermission("teacher",request)){
				return true;
			}
		}

		if(method.isAnnotationPresent(Student.class)){
			if(checkUserPermission("student",request)){
				return true;
			}
		}

		if(method.isAnnotationPresent(Admin.class)){
			if(checkUserPermission("admin",request)){
				return true;
			}
		}

		Map<String,Object> resultMap=new HashMap<>();
		resultMap.put("code",403);
		resultMap.put("message","没有权限");
		response.getWriter().print(JSON.toJSONString(resultMap));
		return false;
	}


	/**
	 * 校验用户使用具有相应的角色,角色是否具备相应的权限
	 * @param request
	 * @param roleName 允许访问的角色名称
	 * @return
	 */
	private boolean checkUserPermission(String roleName,HttpServletRequest request){

		// Spring已经帮我们做了最佳url的匹配,在request的attribute属性的BEST_MATCHING_PATTERN_ATTRIBUTE中
		String url=request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE).toString();
		List<Role> roleList= (List<Role>) request.getAttribute("role");
		// 判断当前用户是否具备允许访问的角色以及角色是否具备该url访问权限
		for(Role role:roleList){
			if(Objects.equals(roleName,role.getRoleName())){
				if(ifRoleHashPermission(roleName,url)){
					return true;
				}
			}
		}
		return false;
	}


	/**
	 * 判断角色是否具备相应的权限
	 * @param roleName
	 * @param url
	 * @return
	 */
	private boolean ifRoleHashPermission(String roleName,String url){

		// 角色的权限集合
		List<Permission> permissionList=(List<Permission>) redisTemplate.opsForHash().get("roleAndPermission",roleName);

		for (Permission permission:permissionList){
			if(Objects.equals(permission.getUrl(),url)){
				return true;
			}
		}
		return false;
	}

}